package com.iwomy.secureplat.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.iwomy.secureplat.admin.api.entity.SysDept;
import com.iwomy.secureplat.common.core.util.R;
import com.iwomy.secureplat.common.data.datascope.DataScope;
import com.iwomy.secureplat.common.data.tenant.TenantContextHolder;
import com.iwomy.secureplat.common.excel.vo.ErrorMessage;
import com.iwomy.secureplat.common.log.annotation.ReckonTime;
import com.iwomy.secureplat.common.security.util.SecurityUtils;
import com.iwomy.secureplat.platform.constant.RedisConstants;
import com.iwomy.secureplat.platform.dto.BasicDeviceDTO;
import com.iwomy.secureplat.platform.dto.BasicInventoryDeviceDTO;
import com.iwomy.secureplat.platform.entity.*;
import com.iwomy.secureplat.platform.mapper.BasicDeviceMapper;
import com.iwomy.secureplat.platform.mapper.BasicInstallLocationMapper;
import com.iwomy.secureplat.platform.service.*;
import com.iwomy.secureplat.platform.utils.DataScopeUtils;
import com.iwomy.secureplat.platform.utils.DeptFillUtils;
import com.iwomy.secureplat.platform.utils.RedisClient;
import com.iwomy.secureplat.platform.utils.RemoteDeptUtils;
import com.iwomy.secureplat.platform.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindingResult;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 设备信息表
 *
 * @author pig
 * @date 2023-11-21 15:14:16
 */
@Service
@Slf4j
public class BasicDeviceServiceImpl extends ServiceImpl<BasicDeviceMapper, BasicDeviceEntity> implements BasicDeviceService {

	@Autowired
	private RemoteDeptUtils remoteDeptUtils;

	@Autowired
	private BasicDeviceEventRecordService basicDeviceEventRecordService;

	@Autowired
	private BasicDeviceAttributeDataService basicDeviceAttributeDataService;

	@Autowired
	private BasicDeviceAttributeService basicDeviceAttributeService;

	@Autowired
	private BasicInstallLocationMapper basicInstallLocationMapper;

	@Autowired
	private AlarmLoggingService alarmLogging;

	@Autowired
	private AlarmFaultLoggingService alarmFaultLogging;

	@Autowired
	private BasicDeviceTypeService deviceTypeService;

	@Autowired
	private BasicDeviceModelService deviceModelService;

	@Autowired
	private BasicAuthorizationRecordService authorizationRecordService;
	@Resource
	private RedisClient redisClient;

	@Override
	@ReckonTime
	public Page<BasicDeviceVO> getBasicDevicePage(Page page, BasicDeviceDTO basicDeviceDTO) {
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(queryWrapper, new DataScope());
		List<Long> deviceId = list.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());

		if (ObjectUtil.isEmpty(deviceId)) return page;

		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper();

		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getDeptLimit())) {
			if (basicDeviceDTO.getDeptLimit() == 20) {
				wrapper.in(BasicDeviceEntity::getDeptId, basicDeviceDTO.getDeptId());
			} else {
				List<SysDept> deptList = (List<SysDept>) remoteDeptUtils.getDescendantList(basicDeviceDTO.getDeptId()).getData();
				List<Long> deptIds = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());
				if (deptIds != null) wrapper.in(BasicDeviceEntity::getDeptId, deptIds);
			}
		} else {
			if (ObjectUtil.isNotEmpty(basicDeviceDTO.getDeptId())) {
				wrapper.in(BasicDeviceEntity::getDeptId, basicDeviceDTO.getDeptId());
			}
		}

		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getDeviceTypeId())) {
			wrapper.eq(BasicDeviceEntity::getDeviceTypeId, basicDeviceDTO.getDeviceTypeId());
		}
		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getDeviceModelId())) {
			wrapper.eq(BasicDeviceEntity::getDeviceModelId, basicDeviceDTO.getDeviceModelId());
		}

		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getLocationId())) {
			wrapper.eq(BasicDeviceEntity::getInstallLocationId, basicDeviceDTO.getLocationId());
		}

		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getBuildingId())) {
			LambdaQueryWrapper<BasicInstallLocationEntity> installLocationWrapper = new LambdaQueryWrapper<>();
			installLocationWrapper.in(BasicInstallLocationEntity::getBuildingId, basicDeviceDTO.getBuildingId());
			List<BasicInstallLocationEntity> installList = basicInstallLocationMapper.selectList(installLocationWrapper);
			List<Long> installIds = installList.stream().map(BasicInstallLocationEntity::getId).collect(Collectors.toList());
			if (!installIds.isEmpty()) {
				wrapper.in(BasicDeviceEntity::getInstallLocationId, installIds);
			} else {
				wrapper.eq(BasicDeviceEntity::getInstallLocationId, installIds);
			}
		}

		if (ArrayUtil.isNotEmpty(basicDeviceDTO.getCreateTime())) {
			wrapper.ge(BasicDeviceEntity::getCreateTime, basicDeviceDTO.getCreateTime()[0]).le(BasicDeviceEntity::getCreateTime,
					basicDeviceDTO.getCreateTime()[1]);
		}
		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getDeviceState())) {
			wrapper.eq(BasicDeviceEntity::getOnline, 20);
			wrapper.eq(BasicDeviceEntity::getDeviceState, basicDeviceDTO.getDeviceState());
		}
		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getUseState())) {
			wrapper.eq(BasicDeviceEntity::getUseState, basicDeviceDTO.getUseState());
		}
		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getBindState())) {
			wrapper.eq(BasicDeviceEntity::getBindState, basicDeviceDTO.getBindState());
		}
		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getStocks())) {
			wrapper.eq(BasicDeviceEntity::getStocks, basicDeviceDTO.getStocks());
		}

		if (StrUtil.isNotEmpty(basicDeviceDTO.getImei())) {
			wrapper.like(BasicDeviceEntity::getImei, basicDeviceDTO.getImei());
		}

		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getImeis())) {
			wrapper.in(BasicDeviceEntity::getId, basicDeviceDTO.getImeis());
		}

		wrapper.in(BasicDeviceEntity::getId, deviceId);

		Page<BasicDeviceVO> basicDevicePage = this.getBaseMapper().selectJoinPage(page, BasicDeviceVO.class, wrapper);
		List<BasicDeviceVO> records = basicDevicePage.getRecords();
		getEnventTime(records);
		DeptFillUtils.fill(basicDevicePage);
		return basicDevicePage;
	}

	@Override
	public BasicDeviceVO getByIds(Long id) {
		// 先判断设备是否已经被删除
		BasicDeviceEntity device = this.getById(id);
		if (device == null || device.getDelFlag().equals(1)) {
			// 如果设备不存在或已经被删除，返回null或抛出异常等处理方式
			return null;
		}
		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper().eq(BasicDeviceEntity::getId, id);
		BasicDeviceVO basicDevice = this.getBaseMapper().selectJoinOne(BasicDeviceVO.class, wrapper);
		if (basicDevice != null) {
			Long deptId = basicDevice.getDeptId();
			if (deptId != null) {
				String deptName = remoteDeptUtils.getDeptName(deptId);
				basicDevice.setDeptName(deptName);
			}
		}

		List<BasicDeviceEventRecordEntity> recordList = basicDeviceEventRecordService.lambdaQuery()
				.eq(BasicDeviceEventRecordEntity::getDeviceId, id)
				.list();
		basicDevice.setRecordList(recordList);

		List<BasicDeviceAttributeDataEntity> attributeDataList = basicDeviceAttributeDataService.lambdaQuery()
				.eq(BasicDeviceAttributeDataEntity::getDeviceId, id)
				.list();

		List<BasicDeviceAttributeDataVO> attributeDataVOList = new ArrayList<>();
		for (BasicDeviceAttributeDataEntity attributeData : attributeDataList) {
			Long attributeId = attributeData.getAttributeId();
			BasicDeviceAttributeEntity attribute = basicDeviceAttributeService.getById(attributeId);
			if (attribute != null) {
				String attributeName = attribute.getAttributeName();
				BasicDeviceAttributeDataVO attributeDataVO = new BasicDeviceAttributeDataVO();
				attributeDataVO.setAttributeName(attributeName);
				attributeDataVO.setDeviceId(attributeData.getDeviceId());
				attributeDataVO.setValue(attributeData.getValue());
				attributeDataVO.setId(attributeData.getId());
				attributeDataVO.setDelFlag(attributeData.getDelFlag());
				attributeDataVOList.add(attributeDataVO);
			}
		}
		basicDevice.setAttributeDataList(attributeDataVOList);

		return basicDevice;
	}

	@Override
	public Page<BasicInventoryDeviceDTO> pageList(Page page, BasicDeviceDTO basicDeviceDTO) {
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(queryWrapper, new DataScope());
		List<Long> deviceId = list.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());

		if (ObjectUtil.isEmpty(deviceId)) return page;

		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper()
				.eq(BasicDeviceEntity::getUseState, 10)
				.eq(BasicDeviceEntity::getStocks, 10)
				.in(BasicDeviceEntity::getId, deviceId);

		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getDeviceTypeId())) {
			wrapper.eq(BasicDeviceEntity::getDeviceTypeId, basicDeviceDTO.getDeviceTypeId());
		}
		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getDeviceModelId())) {
			wrapper.eq(BasicDeviceEntity::getDeviceModelId, basicDeviceDTO.getDeviceModelId());
		}

		if (StrUtil.isNotEmpty(basicDeviceDTO.getImei())) {
			wrapper.like(BasicDeviceEntity::getImei, basicDeviceDTO.getImei());
		}
		return this.getBaseMapper().selectJoinPage(page, BasicInventoryDeviceDTO.class, wrapper);
	}

	@Override
	public DeviceInventoryListVO getDeviceInventoryList(Long id) {
		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper().eq(BasicDeviceEntity::getId, id);
		DeviceInventoryListVO basicDevice = this.getBaseMapper().selectJoinOne(DeviceInventoryListVO.class, wrapper);
		if (basicDevice != null) {
			Long deptId = basicDevice.getDeptId();
			if (deptId != null) {
				String deptName = remoteDeptUtils.getExpensesDeptName(deptId);
				basicDevice.setDeptName(deptName);
			}
		}
		return basicDevice;
	}

	@Override
	public List<BasicDeviceVO> listByScope(BasicDeviceDTO basicDevice) {
		LambdaQueryWrapper<BasicDeviceEntity> wrapper = Wrappers.lambdaQuery();
		if (ObjectUtil.isNotEmpty(basicDevice.getDeptId())) {
			wrapper.eq(BasicDeviceEntity::getDeptId, basicDevice.getDeptId());
			wrapper.like(BasicDeviceEntity::getImei, basicDevice.getImei());
			wrapper.in(BasicDeviceEntity::getBindState, 20);
		}
		if (StrUtil.isNotEmpty(basicDevice.getImeiLike())) {
			wrapper.like(BasicDeviceEntity::getImei, basicDevice.getImeiLike());
			wrapper.in(BasicDeviceEntity::getBindState, 10, 20);
		}

		if (StrUtil.isNotEmpty(basicDevice.getImei())) {
			wrapper.like(BasicDeviceEntity::getImei, basicDevice.getImei());
		}
		if (ObjectUtil.isNotEmpty(basicDevice.getImeis())) {
			wrapper.in(BasicDeviceEntity::getId, basicDevice.getImeis());
		}

		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(wrapper, new DataScope());

		List<BasicDeviceVO> voList = list.stream()
				.map(entity -> {
					BasicDeviceVO vo = new BasicDeviceVO();
					BeanUtil.copyProperties(entity, vo);
					return vo;
				}).collect(Collectors.toList());

		getEnventTime(voList);
		DeptFillUtils.fill(voList);
		return voList;
	}

	@Override
	public BasicDeviceEntity getByImei(String imei) {
		if (StrUtil.isEmpty(imei)) return null;
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(BasicDeviceEntity::getImei, imei);
		queryWrapper.eq(BasicDeviceEntity::getDelFlag, "0");
		queryWrapper.eq(BasicDeviceEntity::getUseState, 10);
		return this.getOne(queryWrapper);
	}

	@Override
	public BasicDeviceEntity getHistoricalImei(String imei) {
		if (StrUtil.isEmpty(imei)) return null;
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(BasicDeviceEntity::getImei, imei);
		queryWrapper.eq(BasicDeviceEntity::getDelFlag, "0");
		return this.getOne(queryWrapper);
	}

	@Override
	public R importDevice(List<BasicDeviceExcelVO> excelVOList, BindingResult bindingResult, Long parentId) {
		List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
		Long tenantId = TenantContextHolder.getTenantId();
		TenantContextHolder.clear();
		//将表格中的每一行数据转换为BasicDeviceExcelVO对象，并提取其中的imei字段：
		List<String> collect = excelVOList.stream().map(BasicDeviceExcelVO::getImei).collect(Collectors.toList());

		Map<String, List<Long>> duplicateRows = new HashMap<>();
		for (long i = 0; i < excelVOList.size(); i++) {
			BasicDeviceExcelVO excelVO = excelVOList.get((int) i);
			String imei = excelVO.getImei();

			if (duplicateRows.containsKey(imei)) {
				duplicateRows.get(imei).add(i + 1);
			} else {
				List<Long> rowList = new ArrayList<>();
				rowList.add(i + 1);
				duplicateRows.put(imei, rowList);
			}
		}
		if (!duplicateRows.isEmpty()) {
			Set<String> errorMsg = new HashSet<>();
			errorMsg.add("表格中imei号重复，不允许新增");

			for (Map.Entry<String, List<Long>> entry : duplicateRows.entrySet()) {
				String imei = entry.getKey();
				List<Long> rowList = entry.getValue();
				if (rowList.size() > 1) {
					for (Long row : rowList) {
						errorMessageList.add(new ErrorMessage(row + 1, errorMsg));
					}
				}
			}
			if (CollUtil.isNotEmpty(errorMessageList) && errorMessageList.stream().anyMatch(e -> CollUtil.isNotEmpty(e.getErrors()))) {
				return R.failed(errorMessageList);
			}
		}

		//使用提取出的imei列表作为条件查询数据库中的BasicDeviceEntity对象集合
		List<BasicDeviceEntity> list = this.list(Wrappers.<BasicDeviceEntity>lambdaQuery().in(BasicDeviceEntity::getImei, collect));
		//将数据库中存在的imei列表提取出来
		List<String> imeiList = list.stream().map(BasicDeviceEntity::getImei).collect(Collectors.toList());
		TenantContextHolder.setTenantId(tenantId);

		excelVOList.stream().forEach(x -> {
			Set<String> errorMsg = new HashSet<>();
			if (imeiList.stream().anyMatch(name -> name.equals(x.getImei()))) {
				errorMsg.add("IMEI号" + x.getImei() + "已存在");
			}
			errorMessageList.add(new ErrorMessage(x.getLineNum(), errorMsg));

			x.setDeptId(SecurityUtils.getUser().getDeptId());
		});

		List<Long> typeIdList = new ArrayList<>();
		List<Long> modelIdList = new ArrayList<>();
		if (parentId.equals(0L)) {
			typeIdList = parentDeviceType(excelVOList, errorMessageList);
			modelIdList = parentDeviceModel(excelVOList, errorMessageList, typeIdList);
		} else {
			typeIdList = deviceType(excelVOList, errorMessageList);
			modelIdList = deviceModel(excelVOList, errorMessageList, typeIdList);
		}

		if (ObjectUtil.isNotEmpty(list) || typeIdList.stream().anyMatch(Objects::isNull) || modelIdList.stream().anyMatch(Objects::isNull)) {
			Map<Long, Set<String>> errorMap = new HashMap<>();
			for (ErrorMessage error : errorMessageList) {
				Long lineNum = error.getLineNum();
				Set<String> errors = error.getErrors();

				// 如果errors为空，则跳过当前循环
				if (!errors.isEmpty()) {
					Set<String> errorSet = errorMap.getOrDefault(lineNum, new HashSet<>());
					errorSet.addAll(errors);
					errorMap.put(lineNum, errorSet);
				}
			}

			List<ErrorMessage> combinedErrors = new ArrayList<>();
			for (Map.Entry<Long, Set<String>> entry : errorMap.entrySet()) {
				Long lineNum = entry.getKey();
				Set<String> errors = entry.getValue();
				String errorMessage = String.join("; ", errors);
				combinedErrors.add(new ErrorMessage(lineNum, Collections.singleton(errorMessage)));
			}

			return R.failed(combinedErrors);
		}
		if (CollUtil.isNotEmpty(errorMessageList) && errorMessageList.stream().anyMatch(e -> CollUtil.isNotEmpty(e.getErrors()))) {
			return R.failed(errorMessageList);
		}
		return R.ok(this.saveBatch(BeanUtil.copyToList(excelVOList, BasicDeviceEntity.class)));
	}

	private MPJLambdaWrapper<BasicDeviceEntity> createBaseWrapper() {
		//多表查询
		return new MPJLambdaWrapper<BasicDeviceEntity>()
				.selectAll(BasicDeviceEntity.class)
				.selectAs(BasicDeviceTypeEntity::getTypeName, BasicDeviceVO::getDeviceType)
				.selectAs(BasicDeviceModelEntity::getDeviceModelName, BasicDeviceVO::getDeviceModelName)
				.leftJoin(BasicDeviceTypeEntity.class, BasicDeviceTypeEntity::getId, BasicDeviceEntity::getDeviceTypeId)
				.leftJoin(BasicDeviceModelEntity.class, BasicDeviceModelEntity::getId, BasicDeviceEntity::getDeviceModelId);

	}

	public Long getDeviceOnlineCount() {
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(queryWrapper, new DataScope());
		List<Long> deviceIdList = list.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());
		if (CollUtil.isEmpty(deviceIdList)) return 0L;
//		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper();
//		wrapper.in(BasicDeviceEntity::getId, deviceId);

//		List<BasicDeviceEntity> deviceEntities = this.baseMapper.selectList(wrapper);
//		long deviceCount = deviceEntities.stream()
//				.filter(entity -> (entity.getOnline() == 20))
//				.count();
		return baseMapper.getDeviceOnlineCount(deviceIdList);
	}

	public Long getDeviceOfflineCount() {
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(queryWrapper, new DataScope());
		List<Long> deviceIdList = list.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());
		if (CollUtil.isEmpty(deviceIdList)) return 0L;
//		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper();
//		wrapper.in(BasicDeviceEntity::getId, deviceId);

//		List<BasicDeviceEntity> deviceEntities = this.baseMapper.selectList(wrapper);
//		long deviceCount = deviceEntities.stream()
//				.filter(entity -> (entity.getOnline() == 10))
//				.count();
		return baseMapper.getDeviceOfflineCount(deviceIdList);
	}

	@Override
	public Long getDeviceNormalCount() {
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(queryWrapper, new DataScope());
		List<Long> deviceIdList = list.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());
		if (CollUtil.isEmpty(deviceIdList)) return 0L;
//		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper();
//		wrapper.in(BasicDeviceEntity::getId, deviceId);

//		List<BasicDeviceEntity> deviceEntities = this.baseMapper.selectList(wrapper);
//		long deviceCount = deviceEntities.stream()
//				.filter(entity -> ((entity.getDeviceState() == 20 && entity.getOnline() == 20) || (entity.getDeviceState() == 40 && entity.getOnline() == 20)))
//				.count();
		return baseMapper.getDeviceNormalCount(deviceIdList);
	}

	@Override
	public Long getDeviceFaultCount() {
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(queryWrapper, new DataScope());
		List<Long> deviceIdList = list.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());
		if (CollUtil.isEmpty(deviceIdList)) return 0L;
//		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper();
//		wrapper.in(BasicDeviceEntity::getId, deviceId);

//		List<BasicDeviceEntity> deviceEntities = this.baseMapper.selectList(wrapper);
		return baseMapper.getDeviceFaultCount(deviceIdList);
	}

	@Override
	public Long getDeviceAlarmCount() {
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(queryWrapper, new DataScope());
		List<Long> deviceIdList = list.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());
		if (CollUtil.isEmpty(deviceIdList)) return 0L;
//		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper();
//		wrapper.in(BasicDeviceEntity::getId, deviceId);

//		List<BasicDeviceEntity> deviceEntities = this.baseMapper.selectList(wrapper);
//		long deviceCount = deviceEntities.stream()
//				.filter(entity -> (entity.getDeviceState() == 40))
//				.count();
		return baseMapper.getDeviceAlarmCount(deviceIdList);
	}

	@Override
	public List<DeviceEventReportEntity> deviceEventReport() {
		return this.baseMapper.deviceEventReport();

	}

	@Override
	public List<ProductRotationVO> productRotation() {
		return this.baseMapper.productRotation(DataScopeUtils.getList());
	}

	@Override
	public List<BasicDeviceEntity> listByScope(LambdaQueryWrapper<BasicDeviceEntity> queryWrapper, DataScope dataScope) {
		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(queryWrapper, dataScope);
		return list;
	}

	@Override
	public List<BasicDeviceModelEntity> homeGetModelListByDevice() {
		TenantContextHolder.setTenantSkip();
		return this.getBaseMapper().homeGetModelListByDevice(DataScopeUtils.getList());
	}

	@Override
	public List<BasicDeviceVO> getdeviceList(BasicDeviceDTO basicDeviceDTO) {
		LambdaQueryWrapper<BasicDeviceEntity> wrapper = Wrappers.lambdaQuery();

		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getImei())) {
			wrapper.like(BasicDeviceEntity::getImei, basicDeviceDTO.getImei());
		}

		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getImeis())) {
			wrapper.in(BasicDeviceEntity::getImei, basicDeviceDTO.getImeis());
		}
		Long deptId = basicDeviceDTO.getDeptId();
		if (ObjectUtil.isEmpty(basicDeviceDTO.getDeptId())) {
			deptId = SecurityUtils.getUser().getDeptId();
		}
		if (ObjectUtil.isNotEmpty(basicDeviceDTO.getDeptLimit())) {
			if (basicDeviceDTO.getDeptLimit() == 20) {
				wrapper.in(BasicDeviceEntity::getDeptId, deptId);
			} else {
				List<SysDept> deptList = (List<SysDept>) remoteDeptUtils.getDescendantList(deptId).getData();
				List<Long> deptIds = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());
				if (deptIds != null) wrapper.in(BasicDeviceEntity::getDeptId, deptIds);
			}
		} else {
			if (ObjectUtil.isNotEmpty(basicDeviceDTO.getDeptId())) {
				wrapper.in(BasicDeviceEntity::getDeptId, basicDeviceDTO.getDeptId());
			}
		}

		List<BasicDeviceEntity> list = this.baseMapper.selectListByScope(wrapper, new DataScope());

		List<BasicDeviceVO> voList = list.stream()
				.map(entity -> {
					BasicDeviceVO vo = new BasicDeviceVO();
					BeanUtil.copyProperties(entity, vo);
					vo.setDeviceType(entity.getDeviceTypeName());
					return vo;
				}).collect(Collectors.toList());

		DeptFillUtils.fill(voList);
		return voList;
	}

	@Override
	public List<BasicDeviceEntity> allModel() {

		return this.baseMapper.allModel(TenantContextHolder.getTenantId(), DataScopeUtils.getList());
	}


	@Override
	public void deactivateDevice(BasicDeviceEntity basicDevice) {
		BasicDeviceEntity device = this.getById(basicDevice.getId());
		if (ObjectUtil.isEmpty(device)) return;
		device.setId(basicDevice.getId());
		device.setRemarks(basicDevice.getRemarks());
		device.setUseState(basicDevice.getUseState());
		device.setOnline(10);
		this.updateById(device);
		redisClient.del(RedisConstants.REDIS_KEY_DEVICE_ONLINE + device.getImei());

	}

	private List<Long> parentDeviceType(List<BasicDeviceExcelVO> excelVOList, List<ErrorMessage> errorMessageList) {
		//设备类型
		List<String> collectType = excelVOList.stream()
				.map(BasicDeviceExcelVO::getDeviceTypeName)
				.collect(Collectors.toList());

		List<BasicDeviceTypeEntity> deviceTypeList = deviceTypeService.list(Wrappers.<BasicDeviceTypeEntity>lambdaQuery()
				.in(BasicDeviceTypeEntity::getTypeName, collectType)
				.eq(BasicDeviceTypeEntity::getState, 10));

		Map<String, Long> deviceTypeIdMap = deviceTypeList.stream()
				.collect(Collectors.toMap(BasicDeviceTypeEntity::getTypeName, BasicDeviceTypeEntity::getId));

		List<Long> typeIdList = excelVOList.stream()
				.map(x -> {
					Set<String> errorMsg = new HashSet<>();
					Long typeId = deviceTypeIdMap.get(x.getDeviceTypeName());
					if (typeId == null) {
						errorMsg.add("设备类型-" + x.getDeviceTypeName() + "不存在");
					} else {
						x.setDeviceTypeId(typeId);
					}
					errorMessageList.add(new ErrorMessage(x.getLineNum(), errorMsg));

					return typeId;
				})
				.collect(Collectors.toList());

		return typeIdList;
	}

	private List<Long> parentDeviceModel(List<BasicDeviceExcelVO> excelVOList, List<ErrorMessage> errorMessageList, List<Long> typeIdList) {
		List<String> collectModel = excelVOList.stream()
				.map(BasicDeviceExcelVO::getDeviceModelName)
				.collect(Collectors.toList());

		List<BasicDeviceModelEntity> modelList = deviceModelService.list(Wrappers.<BasicDeviceModelEntity>lambdaQuery()
				.in(BasicDeviceModelEntity::getDeviceModelName, collectModel)
				.eq(BasicDeviceModelEntity::getState, 10)
				.and(wrapper -> wrapper.in(BasicDeviceModelEntity::getDeviceTypeId, typeIdList)));

		Map<String, Long> deviceModelIdMap = modelList.stream()
				.collect(Collectors.toMap(BasicDeviceModelEntity::getDeviceModelName, BasicDeviceModelEntity::getId));

		List<Long> modelIdList = excelVOList.stream()
				.map(x -> {
					Set<String> errorMsg = new HashSet<>();
					Long modelId = deviceModelIdMap.get(x.getDeviceModelName());
					if (modelId == null) {
						errorMsg.add("设备类型-" + x.getDeviceTypeName() + "对应的设备型号-" + x.getDeviceModelName() + "不存在");
					} else {
						x.setDeviceModelId(modelId);
					}
					errorMessageList.add(new ErrorMessage(x.getLineNum(), errorMsg));

					return modelId;
				})
				.collect(Collectors.toList());
		return modelIdList;
	}

	private List<Long> deviceType(List<BasicDeviceExcelVO> excelVOList, List<ErrorMessage> errorMessageList) {
		//设备类型
		List<String> collectType = excelVOList.stream()
				.map(BasicDeviceExcelVO::getDeviceTypeName)
				.collect(Collectors.toList());

		List<BasicAuthorizationRecordEntity> deviceTypeList = authorizationRecordService.list(Wrappers.<BasicAuthorizationRecordEntity>lambdaQuery()
				.in(BasicAuthorizationRecordEntity::getDeviceTypeName, collectType)
				.in(BasicAuthorizationRecordEntity::getDeptId, SecurityUtils.getUser().getDeptId()));

		Map<String, Long> deviceTypeIdMap = deviceTypeList.stream()
				.collect(Collectors.toMap(BasicAuthorizationRecordEntity::getDeviceTypeName, BasicAuthorizationRecordEntity::getDeviceTypeId));

		List<Long> typeIdList = excelVOList.stream()
				.map(x -> {
					Set<String> errorMsg = new HashSet<>();
					Long typeId = deviceTypeIdMap.get(x.getDeviceTypeName());
					if (typeId == null) {
						errorMsg.add("设备类型-" + x.getDeviceTypeName() + "未授权");
					} else {
						x.setDeviceTypeId(typeId);
					}
					errorMessageList.add(new ErrorMessage(x.getLineNum(), errorMsg));

					return typeId;
				})
				.collect(Collectors.toList());

		return typeIdList;
	}

	private List<Long> deviceModel(List<BasicDeviceExcelVO> excelVOList, List<ErrorMessage> errorMessageList, List<Long> typeIdList) {
		List<String> collectModel = excelVOList.stream()
				.map(BasicDeviceExcelVO::getDeviceModelName)
				.collect(Collectors.toList());

		List<BasicAuthorizationRecordEntity> modelList = authorizationRecordService.list(Wrappers.<BasicAuthorizationRecordEntity>lambdaQuery()
				.in(BasicAuthorizationRecordEntity::getDeviceModelName, collectModel)
				.in(BasicAuthorizationRecordEntity::getDeptId, SecurityUtils.getUser().getDeptId())
				.and(wrapper -> wrapper.in(BasicAuthorizationRecordEntity::getDeviceTypeId, typeIdList)));

		Map<String, Long> deviceModelIdMap = modelList.stream()
				.collect(Collectors.toMap(BasicAuthorizationRecordEntity::getDeviceModelName, BasicAuthorizationRecordEntity::getDeviceModelId));

		List<Long> modelIdList = excelVOList.stream()
				.map(x -> {
					Set<String> errorMsg = new HashSet<>();
					Long modelId = deviceModelIdMap.get(x.getDeviceModelName());
					if (modelId == null) {
						errorMsg.add("设备类型-" + x.getDeviceTypeName() + "对应的设备型号-" + x.getDeviceModelName() + "未授权");
					} else {
						x.setDeviceModelId(modelId);
					}
					errorMessageList.add(new ErrorMessage(x.getLineNum(), errorMsg));

					return modelId;
				})
				.collect(Collectors.toList());
		return modelIdList;
	}

	private List<BasicDeviceVO> getEnventTime(List<BasicDeviceVO> records) {
		records.forEach(record -> {
			// 查询最新的报警和故障记录
			AlarmFaultLoggingEntity alarmFaultLoggingLatest = alarmFaultLogging.lambdaQuery()
					.eq(AlarmFaultLoggingEntity::getDeviceId, record.getId())
					.orderByDesc(AlarmFaultLoggingEntity::getCreateTime)
					.last("LIMIT 1")
					.one();

			AlarmLoggingEntity alarmLoggingLatest = alarmLogging.lambdaQuery()
					.eq(AlarmLoggingEntity::getDeviceId, record.getId())
					.orderByDesc(AlarmLoggingEntity::getCreateTime)
					.last("LIMIT 1")
					.one();

			LocalDateTime latestEventTime = null;

			if (alarmFaultLoggingLatest != null && alarmLoggingLatest != null) {
				latestEventTime = (alarmFaultLoggingLatest.getCreateTime().isAfter(alarmLoggingLatest.getCreateTime()))
						? alarmFaultLoggingLatest.getCreateTime()
						: alarmLoggingLatest.getCreateTime();
			} else if (alarmFaultLoggingLatest != null) {
				latestEventTime = alarmFaultLoggingLatest.getCreateTime();
			} else if (alarmLoggingLatest != null) {
				latestEventTime = alarmLoggingLatest.getCreateTime();
			}
			Optional.ofNullable(latestEventTime).ifPresent(eventTime -> record.setEventTime(eventTime));
		});

		return records;
	}

}